package model;

import java.util.ArrayList;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.state.StateBasedGame;
import controller.Global;

public class GUI {
	private ArrayList<Thumb> thumbnails;
	private Entity grabbed = null;
	private Input input = Global.input;
	private boolean overlay = false;
	private int slide = Global.screenX;
	private boolean ctrl = false;
	private boolean stopProgram = false;

	private class Thumb {
		public Image image;
		public Entity entity;
		public float x, y;
		public float sx, sy;

		public Thumb(Image image, Entity entity) {
			this.image = image;
			this.entity = entity;
		}
	}

	public GUI() {
		thumbnails = new ArrayList<Thumb>();

		// cache menu thumbnails
		for (Entity e : Assets.getInstance().entityMap.values()) {
			thumbnails.add(new Thumb(e.image, e));
		}
	}

	public boolean isProgramStopped() {
		return stopProgram;
	}

	public void keyPressed(int code, char c) {

		if (code == Input.KEY_LCONTROL || code == Input.KEY_RCONTROL) {
			ctrl = true;
		}
		if (input.isKeyDown(Input.KEY_PAUSE)) {
			if (!Global.stage.paused) {
				Global.stage.pause();
			} else {
				Global.stage.unpause();
			}
		}
	}

	public void keyReleased(int code, char c) {

		if (code == Input.KEY_LCONTROL || code == Input.KEY_RCONTROL) {
			ctrl = false;
		}
	}

	public void processInput(StateBasedGame game) {
		Global.mouseX = Global.input.getMouseX();
		Global.mouseY = Global.input.getMouseY();

		if (input.isKeyDown(Input.KEY_Q) && ctrl) {
			stopProgram = true;
		} else if (input.isKeyDown(Input.KEY_ADD)
				|| input.isKeyDown(Input.KEY_EQUALS)) {
			Global.changeScale(-0.5f);
		} else if (input.isKeyDown(Input.KEY_SUBTRACT)
				|| input.isKeyDown(Input.KEY_MINUS)) {
			Global.changeScale(0.5f);
		} else if (input.isKeyDown(Input.KEY_0)) {
			Global.setScale(16.0f);
		} else if (input.isKeyDown(Input.KEY_ESCAPE)) {
			grabbed = null;
		} else if (input.isKeyDown(Input.KEY_DELETE)) {
			if (grabbed != null && grabbed.body != null) {
				Global.world.destroyBody(grabbed.body);
				grabbed = null;
			} else {
				grabbed = null;
			}
		}
	}

	public void mouseWheelMoved(int direction) {
		Global.changeScale(-((float) direction) / 60f);
	}

	public void mouseMoved(int x, int y, int x1, int y1) {

		if (x >= Global.screenX - 1 && !overlay) {
			overlay = true;
			slide = Global.screenX;
		} else if (x < slide && overlay) {
			overlay = false;
		}
	}

	public void mousePressed(int button, int x, int y) {
		Body b;
		Entity data;
		String name = null;
		float dx, dy;
		Vec2 mouse;

		// handle menu icons
		if (Global.mouseX > Global.halfScreenX && overlay) {
			grabbed = null;
			for (Thumb thumb : thumbnails) {
				if (x >= thumb.x && x < thumb.x + thumb.sx && y >= thumb.y
						&& y < thumb.y + thumb.sy) {
					grabbed = thumb.entity.clone();
					break;
				}
			}
			return;
		}

		// handle grabbing and moving objects
		if (grabbed != null && grabbed.body == null && button == 0) {
			Factory.createEntity(grabbed);
		} else if (grabbed != null) {
			grabbed = null;
		} else if (grabbed == null) {
			mouse = Global.screenToWorld(Global.mouseX, Global.mouseY);
			b = Global.world.getBodyList();
			while (b != null) {
				name = null;
				data = (Entity) b.getUserData();
				if (data != null) {
					name = ((Entity) b.getUserData()).name;
					dx = Math.abs(b.getPosition().x - mouse.x);
					dy = Math.abs(b.getPosition().y - mouse.y);
					if (name != null && !name.equals("player")) {

						if ((dx < data.radius && dy < data.radius)
								|| (dx < data.sizeX && dy < data.sizeY)) {
							grabbed = data;
							grabbed.body.setLinearVelocity(new Vec2(0, 0));
							grabbed.body.setAngularVelocity(0);
							break;
						}

					}
				}
				b = b.getNext();
			}
		}
	}

	public void renderMapPullout(Graphics g) {
		int i = 1, row = 0, col = 0;
		float factor = Global.screenX / 20, pad = factor / 5f;
		Image img;

		// draw menu overlay for map editor
		if (overlay) {
			if (slide <= Global.halfScreenX) {
				slide = (int) Global.halfScreenX;
			} else {
				slide -= 50;
			}
		} else {
			if (slide > Global.screenX) {
				slide = Global.screenX;
			} else {
				slide += 50;
			}
		}
		Assets.getInstance().getImage("assets/gfx/grey50.png").draw(slide, 0,
				Global.screenX, Global.screenY);

		g.setColor(new Color(255, 255, 255));
		g.drawString("SELECT AN OBJECT TO PLACE", slide + pad, pad * 2.5f);

		// draw images

		for (Thumb thumb : thumbnails) {
			img = thumb.image;
			row = i / 9;
			col = i - (row * 8);
			thumb.x = slide + (col * pad) + ((col - 1) * factor);
			thumb.y = factor + (row * factor) + (row * pad);
			thumb.sx = factor;
			thumb.sy = factor;

			Assets.getInstance().getImage("assets/gfx/grey50.png").draw(
					thumb.x, thumb.y, factor, factor);

			if (img != null) {
				img.draw(thumb.x, thumb.y, factor, factor);
			}
			g.setColor(new Color(128, 128, 128));
			g.drawRect(thumb.x, thumb.y, factor, factor);
			i++;
		}
	}

	public void renderMouse(Graphics g) {
		float sx, sy;

		if (grabbed != null && grabbed.body != null) {
			Vec2 mouse = Global.screenToWorld(Global.mouseX, Global.mouseY);
			grabbed.body.setXForm(new Vec2(mouse.x, mouse.y), 0f);
			grabbed.body.setLinearVelocity(new Vec2(0, 0));
			grabbed.body.setAngularVelocity(0);
			grabbed.body.wakeUp();
		} else if (grabbed != null && grabbed.body == null) {
			Vec2 m = Global.screenToWorld(Global.mouseX, Global.mouseY);
			grabbed.setPosition(m);
		}

		// draw scaled entity on screen for mouse placement
		if (grabbed != null && grabbed.body == null) {
			if (grabbed.type != Entity.COMPOUND) {
				if (grabbed.type == Entity.CIRCLE) {
					sx = sy = grabbed.radius;
				} else {
					sx = grabbed.sizeX;
					sy = grabbed.sizeY;
				}
				grabbed.image.draw(
						Global.mouseX - (sx * Global.pixelsPerMeter),
						Global.mouseY - (sy * Global.pixelsPerMeter), (sx * 2)
								* Global.pixelsPerMeter, (sy * 2)
								* Global.pixelsPerMeter);
			} else {
				for (Entity e : grabbed.entityList) {
					e.render();
				}
			}
		}
	}

	public void render(Graphics g) {
		renderMapPullout(g);
		renderMouse(g);
	}
}
